package com.zoro.barn.business.service.login.business.normalpassword.controller;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.zoro.barn.api.login.PasswordLoginApi;
import com.zoro.barn.business.service.login.exceptions.PasswordErrorException;
import com.zoro.barn.business.service.login.business.normalpassword.entity.PasswordUser;
import com.zoro.barn.business.service.login.business.normalpassword.exceptions.TokenExpiredBusinessException;
import com.zoro.barn.business.service.login.business.normalpassword.exceptions.TokenIllegalBusinessException;
import com.zoro.barn.business.service.login.business.normalpassword.service.NormalLoginService;
import com.zoro.barn.business.service.login.business.normalpassword.util.token.TokenPayload;
import com.zoro.barn.commons.tools.encryption.EncryptUtils;
import com.zoro.barn.dto.login.PasswordUserDto;
import com.zoro.barn.dto.login.TokenDto;
import org.apache.commons.lang3.StringUtils;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * @author zhaoxingwu
 */
@RestController
@RequestMapping("/ps")
public class PasswordLoginController implements PasswordLoginApi {

    private final NormalLoginService normalLoginService;


    public PasswordLoginController(NormalLoginService normalLoginService) {
        this.normalLoginService = normalLoginService;
    }

    /**
     * 账号密码查询
     *
     * @param dto query parameter
     * @return result
     */
    @RequestMapping
    public PasswordUserDto login(@RequestBody PasswordUserDto dto) throws JsonProcessingException {

        PasswordUser user = normalLoginService.getByAccount(dto.getAccount());
        String password = dto.getPassword();
        if (StringUtils.equals(EncryptUtils.md5Encode(password), user.getPassword())) {
            PasswordUserDto result = new PasswordUserDto();
            result.setAccount(user.getUserAccount());
            result.setUserName(user.getUserName());
            result.setToken(normalLoginService.generateToken(user));
            result.setRefreshToken(normalLoginService.generateRefreshToken(user));
            // 将结果写到Cookie里
            return result;
        }

        throw new PasswordErrorException();
    }

    /**
     * refresh token
     *
     * @param dto dto
     * @return new token
     */
    @RequestMapping("/refresh")
    public PasswordUserDto refresh(@RequestBody PasswordUserDto dto) throws JsonProcessingException {
        if (StringUtils.isNotBlank(dto.getRefreshToken())) {
            PasswordUser user = normalLoginService.checkRefreshToken(dto.getRefreshToken());
            if (user == null) {
                throw new TokenExpiredBusinessException();
            }
            // todo-future 这里可以去验证user 是否被禁用了
            PasswordUserDto result = new PasswordUserDto();
            result.setAccount(user.getUserAccount());
            result.setUserName(user.getUserName());
            result.setToken(normalLoginService.generateToken(user));
            result.setRefreshToken(normalLoginService.generateRefreshToken(user));
            return result;
        }
        throw new TokenIllegalBusinessException();
    }

    /**
     * valid token
     *
     * @param dto dto
     * @return if legal return User otherwise null
     */
    public PasswordUserDto valid(@RequestBody TokenDto dto) {
        String token = dto.getToken();

        try {
            TokenPayload payload = this.normalLoginService.resolveToken(token);
            long exp = payload.getExp();
            long nbf = payload.getNbf();
            if (exp == 0 || nbf == 0) {
                throw new TokenIllegalBusinessException();
            }
            if (System.currentTimeMillis() - nbf > exp) {
                throw new TokenExpiredBusinessException();
            }
            PasswordUserDto result = new PasswordUserDto();
            result.setAccount((String) payload.get("account"));
            result.setUserName((String) payload.get("userName"));
            PasswordUser user = this.normalLoginService.getByAccount(result.getAccount());
            if (StringUtils.isBlank(user.getUserAccount())) {
                throw new TokenIllegalBusinessException();
            }
            result.setPid(user.getPid());
            return result;
        } catch (Exception e) {
            throw new TokenIllegalBusinessException(e);
        }
    }
}
